Skip to content

feat!: Use artifactory catalog - #377

Open
yejseo01 wants to merge 16 commits into
mainfrom
use-artifactory-catalog
Open

feat!: Use artifactory catalog#377
yejseo01 wants to merge 16 commits into
mainfrom
use-artifactory-catalog

Conversation

@yejseo01

@yejseo01 yejseo01 commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

Changes

  • Loads the catalog and schema from Artifactory.
  • Removes the embedded catalog and builtin source.
  • Makes --source always available.
  • Adds shared HTTP fetching for catalog, install, upgrade, and version checks.
  • Fixes the --source registration panic.
  • Adds fetcher tests.

Checklist

  • 🤖 This change is covered by tests as required.
  • 🤹 All required manual testing has been performed.
  • 📖 All documentation updates are complete.

@yejseo01
yejseo01 requested a review from a team as a code owner July 27, 2026 17:07
Comment thread internal/fetch/fetch.go Outdated
Comment thread internal/fetch/fetch.go Outdated
return nil, fmt.Errorf("sending request: %w", err)
}

if response.StatusCode < http.StatusOK || response.StatusCode >= http.StatusMultipleChoices {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not != http.StatusOK?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

well, since we are trying to make it generic, I thought we might want to accept 204 No Content and 206 Partial Content, and the caller would handle such. Can stick to != http.StatusOK if you think that's better?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How would caller handle them right now?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

right now, they just check != http.StatusOK. Maybe you're right, and we won't need it. Will fix it to != http.StatusOK

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done - 09ac673

Comment thread internal/catalog/catalog.go Outdated
Comment thread internal/fetch/fetch.go Outdated
Comment thread cmd/topo/projects.go Outdated
Comment thread internal/catalog/catalog.go Outdated
@muchzill4

Copy link
Copy Markdown
Contributor

Is fix a good category for this? It’s not fixing a bug.

@yejseo01 yejseo01 changed the title fix!: Use artifactory catalog feat!: Use artifactory catalog Jul 28, 2026
Comment thread internal/catalog/catalog.go Outdated
const (
DefaultURL = "https://artifacts.tools.arm.com/devx-topo-project-catalog/" + version + "/catalog/"
DefaultCatalogURL = DefaultURL + "catalog.json"
DefaultSchemaURL = DefaultURL + "catalog.schema.json"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It feels a little unfortunate to download the schema for artifactory every time for every type of source. It means even users who use file:// sources require a network connection + slows the command down to download a static file every time.

Maybe fine for a v1 but wonder if we should consider downloading + embedding the schema version that the CLI supports into the binary? Especially since the catalogDocument type is a mirror of the schema.


Bonus - wonder if we should generate go types based on the schema?!

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Come to think of it, you’re right @awphi, this is a bit wasteful. I wonder if generating types based on the schema would be better. We could also do a pre-flight check of the $schema field in the received catalog - if it matches our expectation.

@yejseo01 yejseo01 Jul 29, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yea I was thinking this on the way back home. For Bartek's suggestion, I'm not sure how that would alleviate user with file:// source from needing network connection? I think to address that, we have no choice but to keep the schema in the same repository

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another thing we can try is to fetch the schema on release of topo, and embed that in the binary on release

@yejseo01
yejseo01 force-pushed the use-artifactory-catalog branch from ed774fc to 5b3f922 Compare July 29, 2026 13:59
@yejseo01

Copy link
Copy Markdown
Contributor Author

for error messages to precisely compare the versions, this PR needs to be merged first to continue - arm/topo-project-catalog#8

@awphi awphi left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice! Have approved arm/topo-project-catalog#8 so we can add the major version check.

Comment thread internal/catalog/catalog.go Outdated

compiler := jsonschema.NewCompiler()
schemaDoc, err := jsonschema.UnmarshalJSON(bytes.NewReader(catalogSchemaJSON))
func parseProjects(ctx context.Context, b []byte) ([]Project, error) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ctx is unused

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good catch

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done - 4088273

Comment thread internal/fetch/fetch.go
Comment on lines +97 to +99
```sh
go run ./scripts/generate_catalog_types v1
```

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Was //go generate not worth the trouble? I kind of like the idea of running all of our codebase dev tasks through standard go-supported paths if possible, not a blocker ofc

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if you like it, no problem using it. I was thinking if someone is not familiar with go generate, it's one less thing for them to read about if we keep it this way though. Basically does the same thing, but with directives, it's more looking up in the internet than just reading the code in my perspective

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On the flipside, it's nicer since you learn what go generate is once, then you can use it across any Go project rather than learning project-specific idioms like go run ./scripts/..., Makefiles, Justfiles or whatever people choose to use. My understanding is that's the whole point of go generate - standardisation.

Comment thread docs/development/DEVELOPMENT.md Outdated

Topo uses the catalog version declared in `internal/catalog/catalog_schema_generated.go`. The same version selects both the catalog and its schema from Artifactory.

Generating the Go types requires Node.js 20 or newer, `npx`, and access to Artifactory. Pass the catalog version to the generator:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it worth calling out access to artifactory? It's public so anyone with an internet connection should have access right?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes. I'll get rid of this mention

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done - 1b69da0

Comment thread scripts/generate_catalog_types/main.go Outdated
const (
quicktypeVersion = "26.0.0"
defaultSchemaBaseURL = "https://artifacts.tools.arm.com/devx-topo-project-catalog/"
generationTimeout = 2 * time.Minute

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is a timeout strictly necessary? Think we can get away without it for an internal dev tool like this that does a pretty simple task

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good catch. I agree

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done - e6921e1

Comment thread scripts/generate_catalog_types/main.go Outdated
Comment on lines +92 to +99
formatted, err := addCatalogVersionConstant(generated, catalogVersion)
if err != nil {
return fmt.Errorf("failed to format quicktype output from schema %q: %w", schemaURL, err)
}
// #nosec G703 -- outputFile is derived from the generator source location.
if err := os.WriteFile(outputFile, formatted, 0o644); err != nil {
return fmt.Errorf("failed to write generated types to %q: %w", outputFile, err)
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is building an AST worth it here? Couldn't we just inject the const at the end of the file? e.g.

Suggested change
formatted, err := addCatalogVersionConstant(generated, catalogVersion)
if err != nil {
return fmt.Errorf("failed to format quicktype output from schema %q: %w", schemaURL, err)
}
// #nosec G703 -- outputFile is derived from the generator source location.
if err := os.WriteFile(outputFile, formatted, 0o644); err != nil {
return fmt.Errorf("failed to write generated types to %q: %w", outputFile, err)
}
formatted := string(generated) + "\n" + "const CatalogMajorVersion = \"" + majorVersion(catalogVersion) + "\"\n"
// #nosec G703 -- outputFile is derived from the generator source location.
if err := os.WriteFile(outputFile, []byte(formatted), 0o644); err != nil {
return fmt.Errorf("failed to write generated types to %q: %w", outputFile, err)
}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess we can? it's just quite awkward to have const at the bottom in my instinct

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yea, I think we should judging by how much code we save

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done - ce1b9fa

Comment thread scripts/generate_catalog_types/main.go Outdated
Comment on lines +134 to +137
func majorVersion(version string) string {
major, _, _ := strings.Cut(version, ".")
return major
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It might be useful to store the full version in the const for us as maintainers if nothing else so we know what version of the schema a given version of the CLI uses without manually diffing our go types vs the source json schema.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree. making this change now. Also we don't have the messge comparing the schema and the catalog version yet. making this as well

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done - b832259

Comment on lines +59 to +62
// Advisory metadata that implementations may use to discover, filter, or suggest suitable
// parameter values. Unknown hint keys should be ignored.
type Hints struct {
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why has this been generated empty? Does quicktype not support patternProperties?

@yejseo01 yejseo01 Jul 31, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh good catch. It seems like patternProperties are not supported in quicktype. Does Hints need to be patternProperties?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants